#pragma once
#include <iostream>
#include <unordered_set>
#include <vector>
#include <string>
#include <signal.h>
#include <functional>
#include "Sock.hpp"
using namespace std;
class HttpServer
{
private:
    int _listensock;
    unordered_set<string> html_save;
    Sock sock;
    unordered_set<int> link_socks;
    vector<pair<int, string>> request_mes; // 客户端请求的信息--第一个参数代表对应的sock，第二个参数代表此客户端发来的信息
public:
    class Http_Request // 内部类
    {
    public:
        HttpServer *hs;
        int sock; // 表示要此线程要管理维护的sock
        Http_Request(HttpServer *HS, int Sock)
            : hs(HS), sock(Sock)
        {
        }
    };
    HttpServer(int port)
    {
        _listensock = sock.Socket();
        sock.Bind(_listensock, port);
        sock.Listen(_listensock);
        cout << "初始化完成" << endl;
        pthread_t t;
        pthread_create(&t, nullptr, Accept, (void *)this);
        cout << "接收sock的线程准备开始任务" << endl;
        AddHtmlMes();
    }
    void AddHtmlMes() // 网页信息填入到html_save中
    {
        vector<string> Mes;
        Mes.push_back("./wwwroot/a/b/haha.html");
        Mes.push_back("./wwwroot/a/index.html");
        Mes.push_back("./wwwroot/index.html");
        int n = Mes.size();
        for (auto &e : Mes)
        {
            html_save.insert(e);
        }
    }
    string Gain_resource_Address(const string &info)
    {
        string target = "./wwwroot/" + info;
        return target;
    }
    void Analyse_Message(const string &address, int newsock)
    {
        ifstream ifs(address);
        string part_info;
        string target_info;
        if (ifs.is_open())
        {
            while (getline(ifs, part_info))
            {
                target_info += part_info;
            }
            ifs.close();
            target_info = "HTTP/1.1 200 OK\r\n\r\n" + target_info;
            send(newsock, target_info.c_str(), target_info.size(), 0);
        }
        else
        {
            cout << newsock << "号套接字" << "访问的路径" << address << "不存在" << endl;
            string tip = "你访问的路径" + address + "不存在";
            tip += "\n";
            send(newsock, tip.c_str(), tip.size(), 0);
        }
    }
    static void *Accept(void *args)
    {
        HttpServer *hs = (HttpServer *)args;
        while (1)
        {
            int newsock = hs->sock.Accept(hs->_listensock, nullptr, nullptr);
            if (newsock >= 0)
            {
                cout << "新链接到来" << endl;
                hs->link_socks.insert(newsock);
                pthread_t t;
                Http_Request hr(hs, newsock);
                pthread_create(&t, nullptr, hs->ReadRequestMes, (void *)&hr); // 创建线程并分配任务
            }
        }
    }
    static void *ReadRequestMes(void *args)
    {
        Http_Request *HR = (Http_Request *)args;
        HttpServer *hm = HR->hs;
        int sock = HR->sock;
        char buffer[10240];
        bool exit = false;
        while (!exit)
        {
            memset(buffer, 0, sizeof buffer);
            int n = recv(sock, buffer, sizeof buffer, 0);
            if (n > 0)
            {
                cout << pthread_self() << "线程" << "从" << sock << "号套接字中接收到了一个信息:" << buffer << endl;
                string request_mes = buffer;
                //    request_mes.pop_back();  //将请求的最后一个字符'\n'去除
                hm->request_mes.push_back({sock, request_mes});
            }
            else // 客户端退出
            {
                for (auto &item : hm->link_socks)
                {
                    if (item == sock)
                    {
                        hm->link_socks.erase(item);
                        cout<<item<<"号套接字退出"<<endl;
                        exit = true;
                    }
                }
            }
        }
        pthread_exit(nullptr); // 结束循环时自动结束线程任务周期
        return nullptr;
    }
    void Run() // 服务端运行主函数只需看看request_mes是否有内容即可
    {

        while (1)
        {
            int size = request_mes.size();
            if (size)
            {
                for (int i = 0; i < size; i++)
                {
                    int sock = request_mes[i].first;
                    string mes = request_mes[i].second;
                    string resource_address = Gain_resource_Address(mes);
                    Analyse_Message(resource_address, sock);
                }
                request_mes.clear();
            }
        }
    }
};